/*
 * hd.h
 *
 *  Created on: 2016-11-11
 *      Author: m
 */

#ifndef SRC_INCLUDE_KERNEL_DRIVER_HD_H_
#define SRC_INCLUDE_KERNEL_DRIVER_HD_H_
#include "type.h"

/*
+-------------------------------------------------------------------------------+
|                        first_hard_disk(master) hd0(0)                         |
|-------------------------------------------------------------------------------|
|       hd1(1)      |      hd2(2)       |      hd3(3)       |       hd4(4)      | 主分区
|-------------------+-------------------+-------------------+-------------------|
|hd1a(16)...hd1p(31)|hd2a(32)...hd2p(47)|hd3a(48)...hd3p(63)|hd4a(64)...hd4p(79)| 逻辑分区
+-------------------+-------------------+-------------------+-------------------+
                    this os install on hd2a

+------------------------------------------------------------------------------------+
|                        second_hard_disk(slave) hd5(5)                              |
|------------------------------------------------------------------------------------|
|       hd6(6)      |       hd7(7)       |        hd8(8)       |        hd9(9)       | 主分区
|-------------------+--------------------+---------------------+---------------------|
|hd6a(80)...hd6p(95)|hd7a(96)...hd7p(111)|hd8a(112)...hd8p(127)|hd9a(128)...hd9p(143)| 逻辑分区
+-------------------+--------------------+---------------------+---------------------+
括号内的值是次设备号
主盘是hd0,其次设备号为0,它的主引导扇区分区表对应的四个分区分别是hd1、hd2、hd3、hd4。
每个扩展分区中最多有16个逻辑分区,以字母a~p表示,逻辑分区的次设备号是以hd1a为基准递增的
这种编号规则的好处是,给定一个次设备号,可以很容易地计算出它是主分区还是扩展分区,或者是哪个扩展分区的哪个逻辑分区。
同时,给定一个分区的名称,我们也很容易计算出其次设备号
*/

#define SECTOR_SIZE         (512)

#define MAX_DRVIVES         (2)         //最多支持两块硬盘
#define NR_PART_PER_DRIVE   (4)         //每块硬盘有四个主分区
#define NR_SUB_PER_PART     (16)        //每个主分区有16个逻辑分区
#define NR_SUB_PER_DRIVE    (4 * 16)    //每块硬盘最多有64个逻辑分区
#define NR_PRIM_PER_DRIVE   (5)         //表示的是hd[0~4]这五个分区,有时把整块硬盘hd0和主分区hd1~4一起看待
#define MAX_PRIM            (9)         //主分区最大值
//我们定义的hd1a的设备号应大于9,这样通过与MAX_PRIM比较,我们就可以知道一个设备是主分区还是逻辑分区
#define HD1A_MINOR          (16)
#define BOOT_MINOR          (32)

#define ROOT_DEV_NO     MAKE_DEV_NO(MAJ_DEV_HD, BOOT_MINOR)

typedef struct {
    u32 start_sect;
    u32 num_sect;
} PART_INFO;

typedef struct {
    int open_cnt;
    PART_INFO primary[5]; // NR_PRIM_PER_DRIVE
    PART_INFO logical[64]; //NR_SUB_PER_DRIVE
} HD_INFO;


void init_hd();
void task_hd();
void hd_handler(int irq_no);
int read_hd_data(int drive, int lba, void* buf, int size);




///**
// * @struct part_ent
// * @brief  Partition Entry struct.
// *
// * <b>Master Boot Record (MBR):</b>
// *   Located at offset 0x1BE in the 1st sector of a disk. MBR contains
// *   four 16-byte partition entries. Should end with 55h & AAh.
// *
// * <b>partitions in MBR:</b>
// *   A PC hard disk can contain either as many as four primary partitions,
// *   or 1-3 primaries and a single extended partition. Each of these
// *   partitions are described by a 16-byte entry in the Partition Table
// *   which is located in the Master Boot Record.
// *
// * <b>extented partition:</b>
// *   It is essentially a link list with many tricks. See
// *   http://en.wikipedia.org/wiki/Extended_boot_record for details.
// */
//struct part_ent {
//    u8 boot_ind;        /**
//                 * boot indicator
//                 *   Bit 7 is the active partition flag,
//                 *   bits 6-0 are zero (when not zero this
//                 *   byte is also the drive number of the
//                 *   drive to boot so the active partition
//                 *   is always found on drive 80H, the first
//                 *   hard disk).
//                 */
//
//    u8 start_head;      /**
//                 * Starting Head
//                 */
//
//    u8 start_sector;    /**
//                 * Starting Sector.
//                 *   Only bits 0-5 are used. Bits 6-7 are
//                 *   the upper two bits for the Starting
//                 *   Cylinder field.
//                 */
//
//    u8 start_cyl;       /**
//                 * Starting Cylinder.
//                 *   This field contains the lower 8 bits
//                 *   of the cylinder value. Starting cylinder
//                 *   is thus a 10-bit number, with a maximum
//                 *   value of 1023.
//                 */
//
//    u8 sys_id;      /**
//                 * System ID
//                 * e.g.
//                 *   01: FAT12
//                 *   81: MINIX
//                 *   83: Linux
//                 */
//
//    u8 end_head;        /**
//                 * Ending Head
//                 */
//
//    u8 end_sector;      /**
//                 * Ending Sector.
//                 *   Only bits 0-5 are used. Bits 6-7 are
//                 *   the upper two bits for the Ending
//                 *    Cylinder field.
//                 */
//
//    u8 end_cyl;     /**
//                 * Ending Cylinder.
//                 *   This field contains the lower 8 bits
//                 *   of the cylinder value. Ending cylinder
//                 *   is thus a 10-bit number, with a maximum
//                 *   value of 1023.
//                 */
//
//    u32 start_sect; /**
//                 * starting sector counting from
//                 * 0 / Relative Sector. / start in LBA
//                 */
//
//    u32 nr_sects;       /**
//                 * nr of sectors in partition
//                 */
//
//} PARTITION_ENTRY;
//
//
///********************************************/
///* I/O Ports used by hard disk controllers. */
///********************************************/
///* slave disk not supported yet, all master registers below */
//
///* Command Block Registers */
///*  MACRO       PORT            DESCRIPTION         INPUT/OUTPUT    */
///*  -----       ----            -----------         ------------    */
//#define REG_DATA    0x1F0       /*  Data                I/O     */
//#define REG_FEATURES    0x1F1       /*  Features            O       */
//#define REG_ERROR   REG_FEATURES    /*  Error               I       */
//                    /*  The contents of this register are valid only when the error bit
//                        (ERR) in the Status Register is set, except at drive power-up or at the
//                        completion of the drive's internal diagnostics, when the register
//                        contains a status code.
//                        When the error bit (ERR) is set, Error Register bits are interpreted as such:
//                        |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                        | BRK | UNC |     | IDNF|     | ABRT|TKONF| AMNF|
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                           |     |     |     |     |     |     |     |
//                           |     |     |     |     |     |     |     `--- 0. Data address mark not found after correct ID field found
//                           |     |     |     |     |     |     `--------- 1. Track 0 not found during execution of Recalibrate command
//                           |     |     |     |     |     `--------------- 2. Command aborted due to drive status error or invalid command
//                           |     |     |     |     `--------------------- 3. Not used
//                           |     |     |     `--------------------------- 4. Requested sector's ID field not found
//                           |     |     `--------------------------------- 5. Not used
//                           |     `--------------------------------------- 6. Uncorrectable data error encountered
//                           `--------------------------------------------- 7. Bad block mark detected in the requested sector's ID field
//                    */
//#define REG_NSECTOR 0x1F2       /*  Sector Count            I/O     */
//#define REG_LBA_LOW 0x1F3       /*  Sector Number / LBA Bits 0-7    I/O     */
//#define REG_LBA_MID 0x1F4       /*  Cylinder Low / LBA Bits 8-15    I/O     */
//#define REG_LBA_HIGH    0x1F5       /*  Cylinder High / LBA Bits 16-23  I/O     */
//#define REG_DEVICE  0x1F6       /*  Drive | Head | LBA bits 24-27   I/O     */
//                    /*  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                        |  1  |  L  |  1  | DRV | HS3 | HS2 | HS1 | HS0 |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                                 |           |   \_____________________/
//                                 |           |              |
//                                 |           |              `------------ If L=0, Head Select.
//                                 |           |                                    These four bits select the head number.
//                                 |           |                                    HS0 is the least significant.
//                                 |           |                            If L=1, HS0 through HS3 contain bit 24-27 of the LBA.
//                                 |           `--------------------------- Drive. When DRV=0, drive 0 (master) is selected.
//                                 |                                               When DRV=1, drive 1 (slave) is selected.
//                                 `--------------------------------------- LBA mode. This bit selects the mode of operation.
//                                                                                    When L=0, addressing is by 'CHS' mode.
//                                                                                    When L=1, addressing is by 'LBA' mode.
//                    */
//#define REG_STATUS  0x1F7       /*  Status              I       */
//                    /*  Any pending interrupt is cleared whenever this register is read.
//                        |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                        | BSY | DRDY|DF/SE|  #  | DRQ |     |     | ERR |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                           |     |     |     |     |     |     |     |
//                           |     |     |     |     |     |     |     `--- 0. Error.(an error occurred)
//                           |     |     |     |     |     |     `--------- 1. Obsolete.
//                           |     |     |     |     |     `--------------- 2. Obsolete.
//                           |     |     |     |     `--------------------- 3. Data Request. (ready to transfer data)
//                           |     |     |     `--------------------------- 4. Command dependent. (formerly DSC bit)
//                           |     |     `--------------------------------- 5. Device Fault / Stream Error.
//                           |     `--------------------------------------- 6. Drive Ready.
//                           `--------------------------------------------- 7. Busy. If BSY=1, no other bits in the register are valid.
//                    */
//#define STATUS_BSY  0x80
//#define STATUS_DRDY 0x40
//#define STATUS_DFSE 0x20
//#define STATUS_DSC  0x10
//#define STATUS_DRQ  0x08
//#define STATUS_CORR 0x04
//#define STATUS_IDX  0x02
//#define STATUS_ERR  0x01
//
//#define REG_CMD     REG_STATUS  /*  Command             O       */
//                    /*
//                        +--------+---------------------------------+-----------------+
//                        | Command| Command Description             | Parameters Used |
//                        | Code   |                                 | PC SC SN CY DH  |
//                        +--------+---------------------------------+-----------------+
//                        | ECh  @ | Identify Drive                  |             D   |
//                        | 91h    | Initialize Drive Parameters     |    V        V   |
//                        | 20h    | Read Sectors With Retry         |    V  V  V  V   |
//                        | E8h  @ | Write Buffer                    |             D   |
//                        +--------+---------------------------------+-----------------+
//
//                        KEY FOR SYMBOLS IN THE TABLE:
//                        ===========================================-----=========================================================================
//                        PC    Register 1F1: Write Precompensation   @     These commands are optional and may not be supported by some drives.
//                        SC    Register 1F2: Sector Count        D     Only DRIVE parameter is valid, HEAD parameter is ignored.
//                        SN    Register 1F3: Sector Number       D+    Both drives execute this command regardless of the DRIVE parameter.
//                        CY    Register 1F4+1F5: Cylinder low + high V     Indicates that the register contains a valid paramterer.
//                        DH    Register 1F6: Drive / Head
//                    */
//
///* Control Block Registers */
///*  MACRO       PORT            DESCRIPTION         INPUT/OUTPUT    */
///*  -----       ----            -----------         ------------    */
//#define REG_DEV_CTRL    0x3F6       /*  Device Control          O       */
//                    /*  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                        | HOB |  -  |  -  |  -  |  -  |SRST |-IEN |  0  |
//                        +-----+-----+-----+-----+-----+-----+-----+-----+
//                           |                             |     |
//                           |                             |     `--------- Interrupt Enable.
//                           |                             |                  - IEN=0, and the drive is selected,
//                           |                             |                    drive interrupts to the host will be enabled.
//                           |                             |                  - IEN=1, or the drive is not selected,
//                           |                             |                    drive interrupts to the host will be disabled.
//                           |                             `--------------- Software Reset.
//                           |                                                - The drive is held reset when RST=1.
//                           |                                                  Setting RST=0 re-enables the drive.
//                           |                                                - The host must set RST=1 and wait for at least
//                           |                                                  5 microsecondsbefore setting RST=0, to ensure
//                           |                                                  that the drive recognizes the reset.
//                           `--------------------------------------------- HOB (High Order Byte)
//                                                                            - defined by 48-bit Address feature set.
//                    */
//#define REG_ALT_STATUS  REG_DEV_CTRL    /*  Alternate Status        I       */
//                    /*  This register contains the same information as the Status Register.
//                        The only difference is that reading this register does not imply interrupt acknowledge or clear a pending interrupt.
//                    */
//
//#define REG_DRV_ADDR    0x3F7       /*  Drive Address           I       */
#endif /* SRC_INCLUDE_KERNEL_DRIVER_HD_H_ */
